/**
 * 错误处理模块 - 统一管理应用中的错误处理、日志记录和用户反馈
 */

import { updateStatus } from './service-worker.js';

/**
 * 错误类型枚举
 */
export const ErrorType = {
  NETWORK: 'network',
  API: 'api',
  STORAGE: 'storage',
  AUTH: 'auth',
  CLIENT: 'client',
  UNKNOWN: 'unknown'
};

/**
 * 错误级别枚举
 */
export const ErrorSeverity = {
  DEBUG: 'debug',
  INFO: 'info',
  WARNING: 'warning',
  ERROR: 'error',
  CRITICAL: 'critical'
};

/**
 * 错误处理类
 */
class ErrorHandler {
  constructor() {
    this.isDevelopment = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
    this.enableLogging = true;
  }

  /**
   * 初始化全局错误处理
   */
  initGlobalErrorHandling() {
    // 处理未捕获的异常
    window.addEventListener('error', (event) => {
      this.handleError(event.error || new Error('未捕获异常'), ErrorType.CLIENT, ErrorSeverity.CRITICAL);
    });

    // 处理未捕获的Promise拒绝
    window.addEventListener('unhandledrejection', (event) => {
      this.handleError(event.reason || new Error('未捕获的Promise拒绝'), ErrorType.CLIENT, ErrorSeverity.ERROR);
    });
  }

  /**
   * 统一错误处理方法
   * @param {Error|string} error - 错误对象或错误信息
   * @param {string} type - 错误类型
   * @param {string} severity - 错误级别
   * @param {Object} context - 错误上下文信息
   */
  handleError(error, type = ErrorType.UNKNOWN, severity = ErrorSeverity.ERROR, context = {}) {
    const errorObj = typeof error === 'string' ? new Error(error) : error;
    const errorInfo = this.createErrorInfo(errorObj, type, severity, context);

    // 记录错误日志
    this.logError(errorInfo);

    // 根据错误级别和类型进行处理
    this.processError(errorInfo);

    // 返回标准化的错误信息，便于调用者使用
    return errorInfo;
  }

  /**
   * 创建标准化的错误信息对象
   */
  createErrorInfo(error, type, severity, context) {
    return {
      id: Date.now().toString(36) + Math.random().toString(36).substr(2),
      message: error.message || '未知错误',
      stack: error.stack || null,
      type,
      severity,
      timestamp: new Date().toISOString(),
      context: {
        url: window.location.href,
        userAgent: navigator.userAgent,
        ...context
      }
    };
  }

  /**
   * 记录错误日志
   */
  logError(errorInfo) {
    if (!this.enableLogging) return;

    const { severity, message, type, stack, context } = errorInfo;

    // 根据错误级别使用不同的日志方法
    switch (severity) {
      case ErrorSeverity.DEBUG:
        if (this.isDevelopment) console.debug(`[DEBUG] [${type}] ${message}`, context);
        break;
      case ErrorSeverity.INFO:
        if (this.isDevelopment) console.info(`[INFO] [${type}] ${message}`, context);
        break;
      case ErrorSeverity.WARNING:
        console.warn(`[WARNING] [${type}] ${message}`, context);
        break;
      case ErrorSeverity.ERROR:
        console.error(`[ERROR] [${type}] ${message}`, context);
        if (stack) console.error(stack);
        break;
      case ErrorSeverity.CRITICAL:
        console.error(`[CRITICAL] [${type}] ${message}`, context);
        if (stack) console.error(stack);
        // 对于严重错误，可以考虑发送到服务器
        this.sendErrorToServer(errorInfo);
        break;
    }
  }

  /**
   * 根据错误类型和级别进行处理
   */
  processError(errorInfo) {
    const { severity, type, message } = errorInfo;

    // 只在生产环境显示用户友好的错误提示
    if (!this.isDevelopment && severity >= ErrorSeverity.ERROR) {
      // 根据错误类型显示不同的用户提示
      switch (type) {
        case ErrorType.NETWORK:
          updateStatus(`网络错误: ${message}`);
          this.showUserNotification('网络连接出现问题，请检查您的网络设置。');
          break;
        case ErrorType.API:
          updateStatus(`服务错误: ${message}`);
          this.showUserNotification('服务器暂时无法响应，请稍后再试。');
          break;
        case ErrorType.STORAGE:
          updateStatus(`存储错误: ${message}`);
          this.showUserNotification('本地存储出现问题，部分功能可能无法使用。');
          break;
        case ErrorType.AUTH:
          updateStatus(`认证错误: ${message}`);
          this.showUserNotification('请重新登录以继续使用。');
          break;
        default:
          if (severity >= ErrorSeverity.CRITICAL) {
            updateStatus(`应用错误: ${message}`);
            this.showUserNotification('应用遇到了问题，我们正在努力修复。');
          }
      }
    }
  }

  /**
   * 显示用户通知
   */
  showUserNotification(message) {
    // 检查是否有通知元素
    let notificationElement = document.getElementById('userNotification');
    
    if (!notificationElement) {
      // 创建通知元素
      notificationElement = document.createElement('div');
      notificationElement.id = 'userNotification';
      notificationElement.style.cssText = `
        position: fixed;
        bottom: 20px;
        left: 50%;
        transform: translateX(-50%);
        background-color: #f44336;
        color: white;
        padding: 12px 20px;
        border-radius: 4px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
        z-index: 10000;
        max-width: 80%;
        text-align: center;
        opacity: 0;
        transition: opacity 0.3s ease;
      `;
      document.body.appendChild(notificationElement);
    }
    
    // 设置消息并显示
    notificationElement.textContent = message;
    notificationElement.style.opacity = '1';
    
    // 3秒后自动隐藏
    setTimeout(() => {
      notificationElement.style.opacity = '0';
    }, 3000);
  }

  /**
   * 发送错误到服务器（在实际应用中实现）
   */
  sendErrorToServer(errorInfo) {
    // 注意：实际应用中应该实现这个方法，但在此示例中我们不执行实际的网络请求
    // 避免在错误处理过程中再次触发网络错误
    console.log('准备发送错误报告到服务器:', errorInfo);
    
    // 在实际项目中，这里可以添加如下代码：
    /*
    try {
      navigator.sendBeacon('/api/error-reports', JSON.stringify({
        ...errorInfo,
        // 可以添加更多的用户信息，但要注意隐私保护
        userId: localStorage.getItem('userId') || 'anonymous'
      }));
    } catch (e) {
      console.error('发送错误报告失败:', e);
    }
    */
  }
}

// 创建单例实例
const errorHandler = new ErrorHandler();

export default errorHandler;
export { ErrorHandler };